package cn.tedu.shoot;

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.applet.AudioClip;
import java.awt.*;
import java.util.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

//整个游戏世界
public class World extends JPanel {
    public static final int WIDTH = 640;
    public static final int HEIGHT = 1024;
    public static final int START = 0;
    public static final int RUNNING = 1;
    public static final int PAUSE = 2;
    public static final int GAME_OVER = 3;
    public int state = START;
    private Sky sky = new Sky();
    private Hero hero = new Hero();
    private FlyingObject[] enemies = {};
    private Bullet[] bullets = {};
    private Boss boss = null;
    private BossBullet[] bossBullets = {};


    /**
     * 生成敌人（小敌机，大敌机，小蜜蜂）对象
     */
    public FlyingObject nextOne() {
        Random rand = new Random();
        int type = rand.nextInt(25);
        if (type < 4) {
            return new Bee();
        } else if (type < 12) {
            return new Airplane();
        }else if(type<20) {
            return new BigAirplane();
        }else{
            return new RandomFly();
        }
    }

    private int enterIndex = 0;// 敌人入场计数

    // 敌人入场
    public void enterAction() {// 每10毫米走一次
        enterIndex++;// 每10毫米增1
        if (enterIndex % 20 == 0) {// 每400（40*10）毫米走一次
            FlyingObject obj = nextOne();// 获取敌人对象
            enemies = Arrays.copyOf(enemies, enemies.length + 1);// 扩容
            enemies[enemies.length - 1] = obj;// 将敌人对象添加到enemies
        }
    }

    private int shootIndex = 0;

    public void shootAction() {
        shootIndex++;
        if (shootIndex % 30 == 0) {
            Bullet[] bs = hero.shoot();
            bullets = Arrays.copyOf(bullets, bullets.length + bs.length);
            System.arraycopy(bs, 0, bullets, bullets.length - bs.length, bs.length);
        }
    }

    private int launchIndex = 0;

    public void launchAction() {
        launchIndex++;
        if (boss != null) {
            if (launchIndex % 60 == 0) {
                BossBullet bots = boss.launch();
                bossBullets = Arrays.copyOf(bossBullets, bossBullets.length + 1);
                bossBullets[bossBullets.length - 1] = bots;

            }
        }
    }


    public void stepAction() {
        sky.step();
        if (boss != null) {
            boss.step();
        }
        for (int i = 0; i < enemies.length; i++) {
            enemies[i].step();
        }
        for (int i = 0; i < bullets.length; i++) {
            bullets[i].step();
        }
        for (int i = 0; i < bossBullets.length; i++) {
            bossBullets[i].step();
        }
    }

    public void outOfBoundsAction() {
        for (int i = 0; i < enemies.length; i++) {
            if (enemies[i].isOutOfBounds() || enemies[i].isRemove()) {
                enemies[i] = enemies[enemies.length - 1];
                enemies = Arrays.copyOf(enemies, enemies.length - 1);

            }
        }
        for (int i = 0; i < bullets.length; i++) {
            if (bullets[i].isOutOfBounds() || bullets[i].isRemove()) {
                bullets[i] = bullets[bullets.length - 1];
                bullets = Arrays.copyOf(bullets, bullets.length - 1);
            }
        }
        if (boss != null) {
            for (int i = 0; i < bossBullets.length; i++) {
                if (bossBullets[i].isOutOfBounds()) {
                    bossBullets[i] = bossBullets[bossBullets.length - 1];
                    bossBullets = Arrays.copyOf(bossBullets, bossBullets.length - 1);
                }
            }
        }
    }

    private int score = 0;

    /**
     * 子弹和敌人的碰撞
     */
    public void bulletBangAction() {
        for (int i = 0; i < bullets.length; i++) {
            Bullet b = bullets[i];
            for (int j = 0; j < enemies.length; j++) {
                FlyingObject f = enemies[j];
                if (b.isLive() && f.isLive() && f.isHit(b)) {
                    b.goDead();
                    f.goDead();
                    if (f instanceof EnemyScore) {
                        EnemyScore es = (EnemyScore) f;
                        score += es.getScore();
                    }
                    if (f instanceof EnemyAward) {
                        EnemyAward ea = (EnemyAward) f;
                        int type = ea.getAwardType();
                        switch (type) {
                            case EnemyAward.FIRE:
                                hero.addFire();
                                hero.addEnergy();
                                break;
                            case EnemyAward.LIFE:
                                hero.addLife();
                                break;
                        }
                    }
                }
            }
        }
    }

    public void bossBulletBangAction() {
        if (boss != null) {
            for (int i = 0; i < bossBullets.length; i++) {
                BossBullet b = bossBullets[i];
                if (b.isLive() && hero.isLive() && b.isHit(hero)) {
                    b.goDead();
                    hero.subtractLife();
                    hero.clearFire();
                }
            }
        }
    }

    public void heroBangAction() {
        for (int i = 0; i < enemies.length; i++) {
            FlyingObject f = enemies[i];
            if (hero.isLive() && f.isLive() && f.isHit(hero)) {
                f.goDead();
                hero.subtractLife();
                hero.clearFire();
            }
        }
    }

    public void bossBangAction() {
        for (int i = 0; i < bullets.length; i++) {
            Bullet b = bullets[i];
            if (boss.isLive() && b.isLive() && b.isHit(boss)) {
                b.goDead();
                boss.subtractLife();
            }

        }
    }

    public void checkGameOverAction() {
        if (hero.getLife() <= 0) {
            state = GAME_OVER;

        }
    }

    public void bossOverAction() {
        if (boss.getLife() <= 0) {
            boss.goDead();
            bossBullets = Arrays.copyOf(bossBullets, 0);
        }
    }



    public void action() {
        MouseAdapter m = new MouseAdapter() {
            public void mouseMoved(MouseEvent e) {
                if (state == RUNNING) {
                    int x = e.getX();
                    int y = e.getY();
                    hero.moveTo(x, y);
                }
            }

            public void mouseClicked(MouseEvent e) {
                switch (state) {
                    case START:
                        state = RUNNING;
                        break;
                    case GAME_OVER:
                        score = 0;
                        sky = new Sky();
                        hero = new Hero();
                        enemies = new FlyingObject[0];
                        bullets = new Bullet[0];
                        state = START;
                        boss = null;
                        bossBullets = new BossBullet[0];
                        break;
                }
                if (hero.getEnergy() > 0) {
                    for (int i = 0; i < enemies.length; i++) {
                        FlyingObject f = enemies[i];
                        f.goDead();
                    }
                    hero.subtractEnergy();
                }

            }

            public void mouseExited(MouseEvent e) {
                if (state == RUNNING) {
                    state = PAUSE;
                }

            }

            public void mouseEntered(MouseEvent e) {
                if (state == PAUSE) {
                    state = RUNNING;
                }

            }
        };
        this.addMouseListener(m);
        this.addMouseMotionListener(m);
        Timer timer = new Timer();// 定时器对象
        int intervel = 10;// 定时间隔（以毫秒为单位）
        timer.schedule(new TimerTask() {
            public void run() {// 定时干的事（每10毫秒走一次）
                if (state == RUNNING) {
                    enterAction();// 敌人入场
                    shootAction();
                    stepAction();
                    outOfBoundsAction();
                    bulletBangAction();
                    heroBangAction();
                    checkGameOverAction();
                    bossBulletBangAction();
                    launchAction();
                    if (boss != null) {
                        bossBangAction();
                        bossOverAction();
                    }
                }
                repaint();// 重画（重新调用paint()方法）
            }
        }, intervel, intervel);// 定时计划

        thread.setDaemon(true);
        thread.start();
    }

    Thread thread = new Thread() {
        @Override
        public void run() {
            try {
                while (true) {
                    Thread.sleep(20000);
                    if(state==RUNNING) {
                        boss = new Boss();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };


    /**
     * 重写paint(）画 g：画笔
     */
    private int energy = hero.getEnergy();
    public void paint(Graphics g) {
        g.drawImage(sky.getImage(), sky.x, sky.y, null);
        g.drawImage(sky.getImage(), sky.x, sky.getY1(), null);
        g.drawImage(hero.getImage(), hero.x, hero.y, null);
        hero.paint(g);
        if (boss != null) {
            boss.paint(g);
        }


        for (int i = 0; i < enemies.length; i++) {
            FlyingObject f = enemies[i];
            g.drawImage(f.getImage(), f.x, f.y, null);
        }
        for (int i = 0; i < bullets.length; i++) {
            FlyingObject b = bullets[i];
            g.drawImage(b.getImage(), b.x, b.y, null);
        }
        for (int i = 0; i < bossBullets.length; i++) {
            BossBullet bo = bossBullets[i];
            g.drawImage(bo.getImage(), bo.x, bo.y, null);
        }

        g.setColor(new Color(255, 255, 255));
        g.setFont(new Font("宋体", Font.BOLD, 20));
        g.drawString("SCORE:" + score, 10, 25);
        g.drawString("LIFE:" + hero.getLife(), 10, 45);
        g.drawString("FIRE:" + hero.getFire(), 10, 83);
        g.drawString("ENERGY:" + hero.getEnergy(), 10, 123);

        g.setColor(new Color(255, 200, 200));
        g.fillRect(10, 50, 100, 18);
        g.setColor(new Color(255, 0, 0));
        for (int i = 0; i < hero.getLife() + 1; i++) {
            g.fillRect(10, 50, hero.getLife() * 4, 18);
        }
        g.setColor(new Color(255, 200, 200));
        g.fillRect(10, 88, 100, 18);
        g.setColor(new Color(0, 0, 255));
        for (int i = 0; i < (hero.getFire()) / 40 + 1; i++) {
            g.fillRect(10, 88, hero.getFire(), 18);
        }
        if (boss != null) {
            if (boss.getLife() > 0) {
                g.drawString("BOSSLIFE:" + boss.getLife(), 120, 45);
                g.setColor(new Color(255, 200, 200));
                g.fillRect(120, 50, 450, 18);
                g.setColor(new Color(255, 0, 0));
            } else {
                return;
            }
            for (int i = 0; i < boss.getLife() + 1; i++) {
                g.fillRect(120, 50, boss.getLife() * 9, 18);
            }
        }


        switch (state) {
            case START:
                g.drawImage(Images.start, 160, 300, null);
                break;
            case PAUSE:
                g.drawImage(Images.pause, 120, 300, null);
                break;
            case GAME_OVER:
                g.drawImage(Images.gameover, 100, 300, null);
                break;

        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH, HEIGHT);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        world.action();
//        new Music("./music1.wav").start();
    }
}
